//
//  AXFModelManager.m
//  AXFEightGroup
//
//  Created by ya on 12/22/16.
//  Copyright © 2016 ya. All rights reserved.
//


#import "AXFModelManager.h"
#import <AFNetworking/AFHTTPSessionManager.h>
#import "AXFDataModel.h"
#import <FMDB/FMDB.h>
#import <YYModel.h>


//#define BaseURL             @"http://iosapi.itcast.cn/loveBeen/"

#define BaseURL                     @"http://iosapi.itcast.cn/loveBeen/"
#define LocationBaseURL             @"http://192.168.43.45/AXFPHP/"






#define _NetworkTool        ([AXFNetworkTool sharedTool])


#define FirstFileName        URLString.link(@".").link(fristKey)
#define SecondFileName       URLString.link(@".").link(secondKey)




#pragma mark - 网络工具类声明

@interface AXFNetworkTool : AFHTTPSessionManager

@property (class, nonatomic, strong, readonly) AXFNetworkTool *sharedTool;

- (void)HTTP_POST:(NSString *)URLString
       parameters:(id)parameters
    completeBlock:(void(^)(id _Nullable responseObject, NSError * _Nullable error))completeBlock;

@end

#pragma mark -





@interface ModelDatabase : NSObject

@property (class, nonatomic, strong, readonly) ModelDatabase    *sharedManager;
@property (nonatomic, strong) FMDatabaseQueue                   *queue;

@end





#pragma mark - 模型管理者


@interface AXFModelManager ()
@property (nonatomic, strong) NSMutableArray<AXFDataModel *> *productList;
@end


#pragma mark -

@implementation AXFModelManager

#pragma mark - 配置

+ (instancetype)sharedManager {
    static id _instance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [[self class] new];
    });
    return _instance;
}


- (instancetype)init
{
    self = [super init];
    if (self) {

    }
    return self;
}

- (void)productListAddModel:(AXFDataModel *)model {
    if ( [self.productList containsObject:model] || model == nil) {
        return;
    }
    [_productList addObject:model];
}

- (void)productListRemoveModel:(AXFDataModel *)model {
    if ( ![self.productList containsObject:model] ) {

        return;
    }
    [_productList removeObject:model];
    NotificationCenterPost(AXFProductCancelNotification, nil, nil);
}

- (NSMutableArray<AXFDataModel *> *)productList {
    if ( _productList == nil ) {
        _productList = [NSMutableArray new];
    }
    return _productList;
}

- (CGFloat)productTotalPrice {

    __block CGFloat totalPrice = 0.0;

    [self.productList enumerateObjectsUsingBlock:^(AXFDataModel * _Nonnull model, NSUInteger idx, BOOL * _Nonnull stop) {
        totalPrice += model.productTotalPrice;
    }];


    return totalPrice;
}


- (NSInteger)productTotalAmount {

    __block NSInteger productTotalAmount = 0;
    [self.productList enumerateObjectsUsingBlock:^(AXFDataModel * _Nonnull model, NSUInteger idx, BOOL * _Nonnull stop) {
        productTotalAmount += model.productAmount;
    }];

    return productTotalAmount;

}

/// Traversing an array

















































- (void)homeData:(void(^)(NSArray<NSArray<AXFDataModel *> *> *models))block {
    __block NSMutableArray *allDataM = [NSMutableArray new];
    [self focus:^(NSArray<AXFDataModel *> * _Nullable models) {
        [allDataM addObject:models];
        [self icons:^(NSArray<AXFDataModel *> * _Nullable models) {
            [allDataM addObject:models];
            [self activities:^(NSArray<AXFDataModel *> * _Nullable models) {
                [allDataM addObject:models];
                [self firstSells:^(NSArray<AXFDataModel *> * _Nullable models) {
                    [allDataM addObject:models];
                    block(allDataM);
                }];
            }];
        }];
    }];
}



- (void)order_goods:( void(^)( NSArray<NSArray<AXFDataModel *> *> *  _Nullable models) )block {

    
    if (block == nil) {
        return;
    }
    
    NSString *file = @"order_goods".link(@"Custom");
    
    id obj = [self readForSandBoxFile:file];
    if (obj) {
        block(obj);
        return;
    }
    
    
    NSString *URLString      = LocationBaseURL.link(@"order_goods");
    NSDictionary *parameters = nil;
    [_NetworkTool HTTP_POST:URLString parameters:parameters completeBlock:^(id  _Nullable responseObject, NSError * _Nullable error) {
        
        NSArray<NSArray *> *order_goodsData = responseObject[@"order_goods"];
        NSMutableArray     *order_goodsArrayM = [NSMutableArray new];

        [order_goodsData enumerateObjectsUsingBlock:^(NSArray * _Nonnull array, NSUInteger idx, BOOL * _Nonnull stop) {






            NSMutableArray *dictModels = [NSMutableArray new];
            [array enumerateObjectsUsingBlock:^(NSDictionary * _Nonnull dict, NSUInteger idx, BOOL * _Nonnull stop) {
                AXFDataModel *model = [[AXFDataModel alloc] initWithDictionary:dict];
                [dictModels addObject:model];
            }];
            [order_goodsArrayM addObject:dictModels];






        }];
        
        block(order_goodsArrayM);
        [self saveToSandBox:order_goodsArrayM filaName:file];

    }];
}


























- (void)loadOrderData:(ModelsBlock)block {
    
    NSString *urlString = @"http://iosapi.itcast.cn/loveBeen/MyOrders.json.php";
    
    NSDictionary *parameters = @{@"call":@"13"};
    
    
    [_NetworkTool HTTP_POST:urlString parameters:parameters completeBlock:^(id  _Nullable responseObject, NSError * _Nullable error) {
        
        if (error) {
            return;
        }
        
        NSArray *dataArray = responseObject[@"data"];
        
        NSArray *arrDetail = [NSArray yy_modelArrayWithClass:[AXFDataModel class] json:dataArray];
        
        NSMutableArray *tempArray1 = [NSMutableArray array];
        [dataArray enumerateObjectsUsingBlock:^(NSDictionary * _Nonnull dict, NSUInteger idx, BOOL * _Nonnull stop) {




            AXFDataModel *model = [[AXFDataModel alloc] initWithDictionary:dict];
            [tempArray1 addObject:model];
            
            NSArray *goodArray = dict[@"order_goods"];
            NSMutableArray *tempArray2 = [NSMutableArray new];
            [goodArray enumerateObjectsUsingBlock:^(NSArray  *_Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
                NSMutableArray *tempArray3 = [NSMutableArray new];
                [obj enumerateObjectsUsingBlock:^(NSDictionary *_Nonnull dict, NSUInteger idx, BOOL * _Nonnull stop) {
                    AXFDataModel *goodModel = [[AXFDataModel alloc] initWithDictionary:dict];
                    [tempArray3 addObject:goodModel];
                }];
                [tempArray2 addObject:tempArray3];
            }];
            [tempArray1 addObject:tempArray2];








        }];
        
        
        for (int i = 0; i < dataArray.count; i++) {
            
            AXFDataModel *model = arrDetail[i];
            
            model.order_goods = tempArray1[i];
            
        }
        block(tempArray1);

    }];
}

- (void)adverts:( ModelsBlock )block {

    NSString *URLString = @"ad.json.php";
    NSDictionary *parameters = @{@"call":@7};


    [_NetworkTool HTTP_POST:URLString parameters:parameters completeBlock:^(NSDictionary *  _Nullable responseObject, NSError * _Nullable error) {
        if (error) {
            return ;
        }
        NSDictionary *dictData = responseObject[@"data"];
        AXFDataModel *model = [[AXFDataModel alloc] initWithDictionary:dictData];
        block(@[model]);
    }];

    return;
}

- (id(^)(id))arr:(id(^)(id obj))block {
    return ^id(id obj) {
        return block(@"");
    };
}







- (void)firstSells:(ModelsBlock)block {
    [self request:@"firstSell.json.php"
       parameters:@{@"call":@2}
         fristKey:@"data"
        secondKey:nil
            block:block];
    return;
}

- (void)focus:(ModelsBlock)block {
    [self request:@"focus.json.php"
       parameters:@{@"call":@1}
         fristKey:@"data"
        secondKey:@"focus"
            block:block];
    return;
}

- (void)helps:(ModelsBlock)block {
    [self request:@"help.json.php"
       parameters:@{@"call":@4}
         fristKey:@"focus"
        secondKey:nil
            block:block];
    return;
}


- (void)mine:(void(^)(NSArray<NSArray *> *mineModels))block {
    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"my.plist" ofType:nil];
    NSArray<NSArray *> *data = [NSArray arrayWithContentsOfFile:filePath];
    
    NSMutableArray *tmpArray = [NSMutableArray new];
    [data sj_operate:^(NSArray * _Nonnull array, NSUInteger idx) {
        
        NSMutableArray *tmpModels = [NSMutableArray new];
        [array sj_operate:^(NSDictionary *  _Nonnull dict, NSUInteger idx) {

            AXFDataModel *model = [[AXFDataModel alloc] initWithDictionary:dict];
            [tmpModels addObject:model];
        }];
        [tmpArray addObject:tmpModels];
    }];
    
    block(tmpArray.copy);
}

- (void)icons:(ModelsBlock)block {
    [self request:@"focus.json.php"
       parameters:@{@"call":@1}
         fristKey:@"data"
        secondKey:@"icons"
            block:block];
    return;
}


- (void)activities:(ModelsBlock)block {
    [self request:@"focus.json.php"
       parameters:@{@"call":@1}
         fristKey:@"data"
        secondKey:@"activities"
            block:block];
    return;
}


- (void)myAdress:(ModelsBlock)block {
    [self request:@"MyAdress.json.php"
       parameters:@{@"call":@12}
         fristKey:@"data"
        secondKey:nil
            block:block];
    return;
}


- (void)myOrders:(ModelsBlock)block {
    [self request:@"MyOrders.json.php"
       parameters:@{@"call":@13}
         fristKey:@"data"
        secondKey:nil
            block:block];
    return;
}


- (void)myCoupon:(ModelsBlock)block {
    [self request:@"MyCoupon.json.php"
       parameters:@{@"call":@9}
         fristKey:@"data"
        secondKey:nil
            block:block];
    return;
}

- (void)promotions:(ModelsBlock)block {
    [self request:@"promotion.json.php"
       parameters:@{@"call":@8}
         fristKey:@"data"
        secondKey:nil
            block:block];
    return;
}

- (void)searchs:(ModelsBlock)block {
    [self request:@"search.json.php"
       parameters:@{@"call":@6}
         fristKey:@"data"
        secondKey:@"hotquery"
            block:block];

    


    return;
}

- (void)categories:(ModelsBlock)block {
    [self request:@"supermarket.json.php"
       parameters:@{@"call":@5}
         fristKey:@"data"
        secondKey:@"categories"
            block:block];
    return;
}

- (void)products:(void(^)(NSDictionary<NSString *, NSArray<AXFDataModel *> *> * _Nullable models))productsBlock {

    if (productsBlock == nil) {
        return;
    }


    NSString *URLString = @"supermarket.json.php";
    NSString *firstKey  = @"data";
    NSString *secondKey = @"products";

    NSDictionary * obj = [self readForSandBoxFile:SecondFileName];

    if (obj.count != 0) {
        productsBlock(obj);
        return;
    }

    
    [self categories:^(NSArray<AXFDataModel *> * _Nullable categroyModels) {




        [_NetworkTool HTTP_POST:URLString parameters:@{@"call":@5} completeBlock:^(id  _Nullable responseObject, NSError * _Nullable error) {

            if (error) {
                return ;
            }
            NSDictionary *responseData = (NSDictionary *)responseObject;
            NSDictionary *dataDict     = responseData[firstKey];
            NSDictionary *productsDict = dataDict[secondKey];

            NSMutableDictionary *tmpDictModelData = [NSMutableDictionary new];
            [categroyModels enumerateObjectsUsingBlock:^(AXFDataModel * _Nonnull model, NSUInteger idx, BOOL * _Nonnull stop) {
                NSString *iD = model.iD;
                NSArray *productArray = productsDict[iD];

                NSMutableArray *tmpProductModels = [NSMutableArray new];
                [productArray enumerateObjectsUsingBlock:^(NSDictionary * _Nonnull product, NSUInteger idx, BOOL * _Nonnull stop) {
                    AXFDataModel *model = [AXFDataModel new];
                    [model setValuesForKeysWithDictionary:product];
                    [tmpProductModels addObject:model];
                }];
                [tmpDictModelData setValue:tmpProductModels forKey:iD];
            }];

            if (productsBlock != nil) {
                [self saveToSandBox:tmpDictModelData filaName:SecondFileName];
                productsBlock(tmpDictModelData);
            }
            return;
        }];


    }];
    return;
}

- (void)systemMessages:(ModelsBlock)block {
    [self request:@"SystemMessage.json.php"
       parameters:@{@"call":@10}
         fristKey:@"data"
        secondKey:nil
            block:block];
    return;
}


- (void)userMessage:(ModelsBlock)block {
    [self request:@"UserMessage.json.php"
       parameters:@{@"call":@11}
         fristKey:@"data"
        secondKey:nil
            block:block];
    return;
}

- (void)request:(NSString *)URLString
     parameters:(id)parameters
       fristKey:(NSString *)fristKey
      secondKey:(NSString *)secondKey
          block:(ModelsBlock)block {

    if (block == nil) {
        return;
    }

    if (fristKey != nil && secondKey == nil) {
        id obj = [self readForSandBoxFile:FirstFileName];
        if (obj) {
            block(obj);
            return;
        }
    } else {
        id obj = [self readForSandBoxFile:SecondFileName];
        if (obj) {
            block(obj);
            return;
        }
    }


    [_NetworkTool HTTP_POST:URLString parameters:parameters completeBlock:^(id  _Nullable responseObject, NSError * _Nullable error) {

        if (error) {
            return ;
        }
        NSDictionary *responseData = (NSDictionary *)responseObject;
        NSDictionary *dictionaryData = nil;
        NSArray<NSDictionary *> *dataArray = nil;

        if (fristKey != nil && secondKey == nil) {
            dataArray = responseData[fristKey];

            [self convertModelWithDataArray:dataArray block:block fileName:FirstFileName];
            return;
        } else {
            dictionaryData = responseData[fristKey];
            dataArray      = dictionaryData[secondKey];

            if ([secondKey isEqualToString:@"hotquery"]) {
                AXFDataModel *model = [AXFDataModel new];
                model.hotquery = (NSArray<NSString *> *)dataArray;
                block(@[model]);
                return;
            }

            [self convertModelWithDataArray:dataArray block:block fileName:SecondFileName];
            return;
        }

    }];

}


- (void)convertModelWithDataArray:(NSArray<NSDictionary *> *)dataArray
                            block:(void(^)(NSArray<AXFDataModel *> *activitiesModels))block
                         fileName:(NSString *)fileName {

    
    
    
    
    
    
    
    
    
    NSMutableArray<AXFDataModel *> *tmpModels = [NSMutableArray new];
    [dataArray enumerateObjectsUsingBlock:^(NSDictionary * _Nonnull dict, NSUInteger idx, BOOL * _Nonnull stop) {
        AXFDataModel *model = [[AXFDataModel alloc] initWithDictionary:dict];
        [tmpModels addObject:model];
    }];
    block(tmpModels.copy);
    [self saveToSandBox:tmpModels filaName:fileName];
    return;
}

#pragma mark -


#pragma mark - 沙盒保存区域


- (void)saveToSandBox:(id)obj filaName:(NSString *)fileName {
    NSString *filePath = [self filePath:fileName];
    if ( ![NSKeyedArchiver archiveRootObject:obj toFile:filePath]) {
        NSLog(@"%s, error.", __func__);
    }
}

- (id)readForSandBoxFile:(NSString *)fileName {
    NSString *filePath = [self filePath:fileName];
    id obj = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
    if ([obj isKindOfClass:[NSArray class]]) {
        NSArray *array = (NSArray *)obj;
        if (array.count == 0) {
            return nil;
        }
    }
    return obj;
}

- (NSString *)filePath:(NSString *)fileName {
    NSString *filePath = DocumentDirectory().link(@"/").link(fileName).suffix(@"plist");
    return filePath;
}


#pragma mark -


#pragma mark - 测试专区


- (void)test {


//    [_ModelMgr order_goods:^(NSArray<NSArray<AXFDataModel *> *> * _Nullable models) {
////        NSLog(@"=======%@", models[0][0].img);
//    }];
    

}


#pragma mark -

@end













#pragma mark - 网络工具类实现


@implementation AXFNetworkTool

#pragma mark - 配置


+ (instancetype)sharedTool {
    static AXFNetworkTool * _instance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [AXFNetworkTool manager];

        NSURL *baseURL = [NSURL URLWithString:BaseURL];
        NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
        _instance = [[AXFNetworkTool alloc] initWithBaseURL:baseURL sessionConfiguration:configuration];
        
        
        _instance.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript", @"text/html", @"text/plain", nil];
        
        
        
        
        _instance.requestSerializer = [AFJSONRequestSerializer serializer];
        _instance.requestSerializer.timeoutInterval = 30.0;
    });
    return _instance;
}


- (void)HTTP_POST:(NSString *)URLString parameters:(id)parameters completeBlock:(void(^)(id _Nullable responseObject, NSError * _Nullable error))completeBlock {

    [self POST:URLString parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        completeBlock(responseObject, nil);
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        NSLog(@"错误: %@, %s", error, __func__);
        completeBlock(nil, error);
    }];
}

#pragma mark -

@end


#pragma mark -


#pragma mark - 数据库实现

@implementation ModelDatabase

+ (instancetype)sharedManager {
    static id _instance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [[self class] new];
    });
    return _instance;
}


- (instancetype)init
{
    self = [super init];
    if (self) {
        self.queue = [FMDatabaseQueue databaseQueueWithPath:DocumentDirectory().link(@"/").link(BundleName()).suffix(@"db")];
        [self setup];
    }
    return self;
}

- (void)setup {

}


#if 0

    /** To perform queries and updates on multiple threads, you'll want to use `FMDatabaseQueue`.
     要在多个线程上执行查询和更新, 你需要使用 FMDatabaseQueue

     Using a single instance of `<FMDatabase>` from multiple threads at once is a bad idea.  It has always been OK to make a `<FMDatabase>` object *per thread*.  Just don't share a single instance across threads, and definitely not across multiple threads at the same time.
     在多线程使用一个单例 FMDatabase 是一个坏主意. 一个数据库一个线程是好的, 不要跨线程共享单个实例. 绝对不能同时跨多个线程.
     

     Instead, use `FMDatabaseQueue`. Here's how to use it:
     相反, 使用 FMDatabaseQueue. 以下是使用方法:

     First, make your queue.
     首先, make 一个queue.

     FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:aPath];

     Then use it like so:
     像下面这样使用它:

     [queue inDatabase:^(FMDatabase *db) {
     [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:1]];
     [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:2]];
     [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:3]];

     FMResultSet *rs = [db executeQuery:@"select * from foo"];
     while ([rs next]) {
     //…
     }
     }];

     An easy way to wrap things up in a transaction can be done like this:
     一个简单的方法来包装事务, 在事务中可以这样做:

     [queue inTransaction:^(FMDatabase *db, BOOL *rollback) {
     [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:1]];
     [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:2]];
     [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:3]];

     if (whoopsSomethingWrongHappened) {
     *rollback = YES;
     return;
     }
     // etc…
     [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:4]];
     }];

     `FMDatabaseQueue` will run the blocks on a serialized queue (hence the name of the class).  So if you call `FMDatabaseQueue`'s methods from multiple threads at the same time, they will be executed in the order they are received.  This way queries and updates won't step on each other's toes, and every one is happy.
     `FMDatabaseQueue`将在一个序列化队列上运行blocks, 因此, 如果你在同一时间从多个线程调用`FMDatabaseQueue`的方法, 他们将按照他们被接受的顺序执行.
     

     ### See also

     - `<FMDatabase>`

     @warning Do not instantiate a single `<FMDatabase>` object and use it across multiple threads. Use `FMDatabaseQueue` instead.
     不要实例化一个`FMDatabase`对象, 并在多线程中使用它. 使用`FMDatabaseQueue`.
     

     @warning The calls to `FMDatabaseQueue`'s methods are blocking.  So even though you are passing along blocks, they will **not** be run on another thread.
     对`FMDatabaseQueue`的方法的调用是模块化的. 他们不会在另一个线程上运行.
     */

#endif



@end

#pragma mark -
#if 0



#endif
